/*
  Copyright 2009 Colin Prinn

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package net.recursv.motific.unittest;

import net.recursv.motific.unittest.impl.__TestSuite;

/**
 * Created by: recursv
 * Date: 31/07/2009
 * Time: 9:25:47 PM
 */
class TestRunner extends Thread {
    private TestSuiteIterator _iterator;
    private boolean _alive = true;
    private String _testName = "Initialising...";
    private int _testNumber = 0;
    private TestMidlet _testMidlet;
    private static final String TEAR_DOWN = " -> afterTest";
    private static final String TEST_SUITE_FINALISE = "Test suite finalise";
    private static final String SETUP = " -> beforeTest";
    private static final String TEST_SUITE_PREPARATION = "Test suite preparation";
    private static final String FRAMEWORK_ERROR = "Framework error";
    private static final String THIS_SHOULD_NEVER_HAPPEN = "This should never happen";
    private static final String COMPLETED_ALL_TESTS = "Completed running tests.";

    TestRunner(TestMidlet testMidlet, TestSuiteIterator iterator) {
        _testMidlet = testMidlet;
        _iterator = iterator;
    }

    public void run() {
        StringBuffer errorNameBuffer = new StringBuffer();
        __TestSuite suite;
        boolean passed;

        try {
            for (suite = _iterator.getNextTestSuite(); _alive && suite != null; suite = _iterator.getNextTestSuite()) {
                try {
                    suite.prepare();
                } catch (Throwable throwable) {
                    _testMidlet.addResult(throwable, suite.getSuiteName(), TEST_SUITE_PREPARATION);
                    continue;
                }
                for (passed = true; suite.hasMore(); passed = true) {
                    _testNumber++;
                    _testName = suite.getNextTestName();

                    try {
                        suite.beforeTest();
                    } catch (Throwable throwable) {
                        _testMidlet.addResult(throwable, suite.getSuiteName(), errorNameBuffer.delete(0, errorNameBuffer.length()).append(_testName).append(SETUP).toString());
                        continue;
                    }
                    try {
                        suite.runNextTest();
                    } catch (Throwable e) {
                        _testMidlet.addResult(e, suite.getSuiteName(), _testName);
                        passed = false;
                    }
                    try {
                        suite.afterTest();
                    } catch (Throwable e) {
                        _testMidlet.addResult(e, suite.getSuiteName(), errorNameBuffer.delete(0, errorNameBuffer.length()).append(_testName).append(TEAR_DOWN).toString());
                        passed = false;
                    }
                    if (passed)
                        _testMidlet.addResult(suite.getSuiteName(), _testName);
                    _testMidlet.notifyCompletedTestCase();
                }
                try {
                    suite.finalise();
                } catch (Throwable throwable) {
                    _testMidlet.addResult(throwable, suite.getSuiteName(), TEST_SUITE_FINALISE);
                }
                _testMidlet.notifyCompletedTestSuite();
            }
        } catch (Throwable t) {
            _testMidlet.addResult(t, FRAMEWORK_ERROR, THIS_SHOULD_NEVER_HAPPEN);
        } finally {
            _alive = false;
            _testMidlet.notifyCompletedAllTests();
            _testName = COMPLETED_ALL_TESTS;
        }
    }

    public void cease() {
        _alive = false;
    }

    public String getTestName() {
        return _testName;
    }

    public int getTestNumber() {
        return _testNumber;
    }
}